package org.zhuzx.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * 返回结果的通用格式封装，以code=0为成功标志，以泛型对象存放额外数据体data。<br>
 * 本类适用于数据查询的交互场景，因为查询一般都需要在data中返回对象数据。<br>
 * 若是只需要知道结果成功与否的交互场景，可以使用更加简便的{@link Result}类，不需要声明泛型。
 * @author zhuzx 2022-10-19
 */
@ApiModel("通用返回格式")
public class GenericResult<T> extends AbstractResult {

	@ApiModelProperty(value = "状态码，" + SUCCESS_CODE_VALUE + "为成功，其它为失败。", position = 1)
	protected int code;

	@ApiModelProperty(value = "额外的数据体", position = 3)
	protected T data;

	/** 基于json字符串构建时，存储原始的json文本。*/
	@JSONField(serialize = false)
	@JsonIgnore
	protected String originalJson;

	protected static final int SUCCESS_CODE_VALUE = 0;
	protected static final int FAIL_CODE_VALUE = -1;

	protected GenericResult() {}

	public GenericResult(int code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	public GenericResult(int code, String msg, T data) {
		this(code, msg);
		this.data = data;
	}

	public static <T> GenericResult<T> newSuccessGenericResult(T data) {
		return new GenericResult<>(SUCCESS_CODE_VALUE, SUCCESS_MSG_VALUE, data);
	}

	public static <T> GenericResult<T> newFailGenericResult(String msg) {
		return new GenericResult<>(FAIL_CODE_VALUE, msg);
	}

	/**
	 * 解析远程接口返回的json字符串，得到一个对象。
	 * @param dataBodyClass data字段的对象类型
	 */
	public static <T> GenericResult<T> parseGenericResult(String responseJson, Class<T> dataBodyClass) {
		assertCodeExistAndTypeMatched(JSON.parseObject(responseJson).get("code"));
		GenericResult<T> result = JSON.parseObject(responseJson,
				new TypeReference<GenericResult<T>>(dataBodyClass) {});
		result.originalJson = responseJson;
		return result;
	}

	protected static void assertCodeExistAndTypeMatched(Object code) {
		if (!(code instanceof Integer)) {
			throw new IllegalArgumentException("解析json失败：" +
					((code == null) ? "缺失code属性" : "code必须是int值"));
		}
	}

	@JSONField(serialize = false)
	@JsonIgnore
	@Override
	public boolean isSuccess() {
		return code == SUCCESS_CODE_VALUE;
	}

	@Override
	public GenericResult<T> assertSuccess(String bizErrMsgPrefix) {
		super.assertSuccess(bizErrMsgPrefix);
		return this;
	}

	public int getCode() {
		return code;
	}

	public GenericResult<T> setData(T data) {
		this.data = data;
		return this;
	}

	@Override
	public T getData() {
		return data;
	}

	@Override
	public T assertSuccessAndGetData() {
		return assertSuccess(null).getData();
	}
	
	/**
	 * 返回json，若这个Result对象是从json解析来的，则会使用内部缓存的原始json串直接返回，以避免序列化的消耗。
	 */
	@Override
	public String toString() {
		return originalJson == null ? JSON.toJSONString(this) : originalJson;
	}

}